package com.typedef.helper;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.Activity;
import android.content.Context;
import android.hardware.usb.UsbManager;
import android.util.Log;

import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.HexDump;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import com.typedef.basichumingbirdcontroller.R;

public class UsbConectionHelper {
	
	static private final String TAG = UsbConectionHelper.class.getSimpleName();
	
	private UsbSerialDriver mSerialDevice; // The device currently in use, or {@code null}.
    private UsbManager mUsbManager; //The system's USB service.
    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
    private SerialInputOutputManager mSerialIoManager;
    private Activity act = null;
    private Integer baudRate, dataBits, stopBits, parity;
    
    private enum statusEnum {
        STATUS_NO_DEVICE_FOUND, 
        STATUS_CONNECTED,
        STATUS_DISCONNECTED;
    };    
    
    public UsbConectionHelper(Activity act, Integer baudRate, Integer dataBits, Integer stopBits, Integer parity){
     	mUsbManager = (UsbManager) act.getSystemService(Context.USB_SERVICE);
     	this.act = act;
     	this.baudRate = baudRate;
     	this.dataBits = dataBits;
     	this.stopBits = stopBits;
     	this.parity = parity;
    }
    
    public String createConn(){
    	this.mSerialDevice = UsbSerialProber.acquire(mUsbManager);
        Log.d(TAG, "Started, mSerialDevice=" + mSerialDevice);
        if (mSerialDevice == null) {
            return "No serial device.";
        } 
        
        try {
        	mSerialDevice.open();

        	mSerialDevice.setParameters(
        			this.baudRate, 
        			this.dataBits, 
        			this.stopBits,
        			this.parity);

        } catch (IOException e) {
        	Log.e(TAG, "Error setting up device: " + e.getMessage(), e);
        	try {
        		mSerialDevice.close();
        	} catch (IOException e2) {}
        	mSerialDevice = null;
        	return String.valueOf(this.act.getText(R.string.frag_conn_error)) + e.getMessage();
        }

        onDeviceStateChange();
        return String.valueOf(act.getText(R.string.frag_conn_device)) + mSerialDevice;
    }
    
    private final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() {
        @Override
        public void onRunError(Exception e) {
            Log.d(TAG, "Runner stopped.");
        }

        @Override
        public void onNewData(final byte[] data) {
        	act.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                	updateReceivedData(data);
                }
            });
        }
    };
    
    public void stopDevice(){
    	stopIoManager();
        if (mSerialDevice != null) {
            try {
                mSerialDevice.close();
            } catch (IOException e) {
                // Ignore.
            }
            mSerialDevice = null;
        }	
    }
    
    private void stopIoManager() {
        if (mSerialIoManager != null) {
            Log.i(TAG, "Stopping io manager ..");
            mSerialIoManager.stop();
            mSerialIoManager = null;
        }
    }

    private void startIoManager() {
        if (mSerialDevice != null) {
            Log.i(TAG, "Starting io manager ..");
            mSerialIoManager = new SerialInputOutputManager(mSerialDevice, mListener);
            mExecutor.submit(mSerialIoManager);
        }
    }

    private void onDeviceStateChange() {
        stopIoManager();
        startIoManager();
    }

    private void updateReceivedData(byte[] data) {
        final String message = "Read " + data.length + " bytes: \n"
                + HexDump.dumpHexString(data) + "\n\n";
        Log.i(TAG, message);
        //mDumpTextView.append(message);
        //mScrollView.smoothScrollTo(0, mDumpTextView.getBottom());
    }
    
    public void send(byte[] inf){ 
    	try {
			mSerialDevice.write(inf, 500);
		} catch (IOException e) {
			Log.i(TAG, e.getMessage());
		}
    }
}
